#include "calculate.h"
#include <QTime>
#include <QString>
#include <bits/stdc++.h>
//出栈操作
#define top_and_pop(stack, var) var=stack.top();stack.pop()
using namespace std;

Calculate::Calculate()
{
    qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
    r=0;
}

//运算 + - * / , 数量 num_n = 4 max_oper 最多的运算结果
const int num_n = 4, max_oper = 1 << (2*num_n - 2);
// 候选的后缀表达式所代表的整数值
int methods[5] = {0b101010, 0b101100, 0b110010, 0b110100, 0b111000};

//用于设置四个数字
void Calculate::setNum(){
    for(int i=0;i<4;i++){
        arr[i] = RandomNum();
    }
    int count = 0;
    sort(arr, arr + num_n);
        do {
            for(int meth : methods) {
                for(int oper = 0; oper < max_oper; oper++) {
                    if(hasAnswer(arr, oper, meth)) {
                        count++;
                    }
                }
            }
        } while(next_permutation(arr, arr + num_n));
    if(count==0){
        setNum();
    }
}
//用于生成1-9的随机数
int Calculate::RandomNum(){
    int rand = qrand() % 9 + 1;
    return rand;
}

//得到数字
int Calculate::getNum(int index){
    return arr[index];
}

//得到答案
string Calculate::getResult(int index){
    return s[index];
}

int Calculate::getResultCount(){
    return r;
}

struct Num {
    int a, b;
    Num(int ta = 0, int tb = 1) : a(ta), b(tb) {
        if(b < 0)
        {
            a = -a;
            b = -b;
        }
        int g = __gcd(abs(a), b);
        a /= g;
        b /= g;
    }
};


//判断是否有答案
bool Calculate::hasAnswer(int* arr, int oper_code, int method) {
    stack<int> ops;
    stack<Num> nums;
    int arr_pos = 0;
    nums.push(Num(arr[arr_pos++]));
    while(method) {
        if(method & 1) {
            Num x,y;
            top_and_pop(nums, y);
            top_and_pop(nums, x);
            switch(ops.top()) {
            case 0: // +
                nums.push({x.a * y.b + x.b * y.a, x.b * y.b});
                break;
            case 1: // -
                nums.push({x.a * y.b - x.b * y.a, x.b * y.b});
                break;
            case 2: // *
                nums.push({x.a * y.a, x.b * y.b});
                break;
            case 3: // /
                if(y.a == 0)
                    return false;
                nums.push({x.a * y.b, x.b * y.a});
                break;
            }
            ops.pop();
        } else {
            nums.push(Num(arr[arr_pos++]));
            ops.push(oper_code & 3);
            oper_code >>= 2;
        }
        method >>= 1;
    }
    return nums.top().a == 24 && nums.top().b == 1;
}

//打印答案
void Calculate::printAnswer(int* arr, int oper_code, int method) {
    const char* operstr = "+-*/";
    string zuo = "(", you = ")", s1, s2;
    stack<char> ops;
    stack<string> str;
    int arr_pos = 0;
    str.push(to_string(arr[arr_pos++]));
    while(method) {
        if(method & 1) {
            top_and_pop(str, s2);
            top_and_pop(str, s1);
            str.push(zuo + s1 + ops.top() + s2 + you);
            ops.pop();
        } else {
            str.push(to_string(arr[arr_pos++]));
            ops.push(operstr[oper_code & 3]);
            oper_code >>= 2;
        }
        method >>= 1;
    }
    string res = str.top();
    s[r]=res.substr(1, res.length() - 2);
    r++;
}

void Calculate::Answer() {
    //令r为0
    r = 0;
    sort(arr, arr + num_n);
        do {
            for(int meth : methods) {
                for(int oper = 0; oper < max_oper; oper++) {
                    if(hasAnswer(arr, oper, meth)) {
                        printAnswer(arr, oper, meth);
                    }
                }
            }
        } while(next_permutation(arr, arr + num_n));
}
